#include <defs.h>
#include <unistd.h>
#include <stdarg.h>
#include <syscall.h>

#define MAX_ARGS            5

/**
 * 执行系统调用的封装函数
 * 该函数使用可变参数列表和内联汇编来处理系统调用，旨在提供一种通用的方法
 * 来调用操作系统提供的服务，同时确保代码的可移植性和效率
 * 
 * @param num 系统调用号，用于指定请求操作系统执行的具体操作
 * @param ... 可变参数列表，包含系统调用所需的参数
 * @return 系统调用的返回值，其含义取决于具体的系统调用
 * 
 * 注意：此函数假设系统调用号和参数的数量是正确的，且不会进行错误检查
 * MAX_ARGS 定义了系统调用可接受的最大参数数量，超过此数量的参数将被忽略
 * T_SYSCALL 是中断向量号，用于触发系统调用中断
 */
static inline int
syscall(int num, ...) {
    // 初始化可变参数列表
    va_list ap;
    va_start(ap, num);

    //a数组用于存储系统调用的参数
    uint32_t a[MAX_ARGS];
    int i, ret;

    // 将可变参数列表中的参数提取到a数组中
    for (i = 0; i < MAX_ARGS; i ++) {
        a[i] = va_arg(ap, uint32_t);
    }

    // 结束可变参数列表的使用
    va_end(ap);

    // 使用内联汇编执行系统调用
    // "int %1" 触发中断，执行系统调用
    // "=a" (ret) 指定eax寄存器用于接收系统调用的返回值
    // "i" (T_SYSCALL) 指定中断向量号
    // "a" (num) 将系统调用号放入eax寄存器
    // "d" (a[0])、"c" (a[1])、"b" (a[2])、"D" (a[3])、"S" (a[4]) 将参数放入相应的寄存器
    // "cc" 表示中断会改变条件码，"memory" 表示中断可能会修改任意内存位置的值
    asm volatile (
        "int %1;"
        : "=a" (ret)
        : "i" (T_SYSCALL),
          "a" (num),
          "d" (a[0]),
          "c" (a[1]),
          "b" (a[2]),
          "D" (a[3]),
          "S" (a[4])
        : "cc", "memory");
    // 返回系统调用的结果
    return ret;
}

int
sys_exit(int error_code) {
    return syscall(SYS_exit, error_code);
}

int
sys_fork(void) {
    return syscall(SYS_fork);
}

int
sys_wait(int pid, int *store) {
    return syscall(SYS_wait, pid, store);
}

int
sys_yield(void) {
    return syscall(SYS_yield);
}

int
sys_kill(int pid) {
    return syscall(SYS_kill, pid);
}

int
sys_getpid(void) {
    return syscall(SYS_getpid);
}

int
sys_putc(int c) {
    return syscall(SYS_putc, c);
}

int
sys_pgdir(void) {
    return syscall(SYS_pgdir);
}

